package org.flik.server.bean;

import java.util.List;
import java.util.Map;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateless
@LocalBean
public class GenericBean {
	@PersistenceContext
	private EntityManager em;

	public <T> T create(T t) {
		em.persist(t);
		return t;
	}

	public <T> T find(Class<T> type, Object id) {
		return em.find(type, id);
	}

	public <T> T findDetached(Class<T> type, Object id) {
		T entityInstance = find(type, id);
		em.detach(entityInstance);
		return entityInstance;
	}
	
	
	public <T> void delete(T t) {
		t = em.merge(t);
		em.remove(t);
	}

	public <T> T update(T t) {
		return em.merge(t);
	}
	
	@SuppressWarnings("rawtypes")
	public List findWithNamedQuery(String queryName) {
		return em.createNamedQuery(queryName).getResultList();
	}

	@SuppressWarnings("rawtypes")
	public List findWithNamedQuery(String queryName, int resultLimit) {
		return em.createNamedQuery(queryName).setMaxResults(resultLimit)
				.getResultList();
	}

	@SuppressWarnings("rawtypes")
	public List findWithNamedQuery(String namedQueryName,
			Map<String, Object> parameters) {
		return findWithNamedQuery(namedQueryName, parameters, -1, 0);
	}

	@SuppressWarnings("rawtypes")
	public List findWithNamedQuery(String namedQueryName,
			Map<String, Object> parameters, int firstResult, int resultLimit) {
		Query query = this.em.createNamedQuery(namedQueryName);
		if (firstResult > -1)
			query.setFirstResult(firstResult);
		if (resultLimit > 0) 
			query.setMaxResults(resultLimit);
		for (Map.Entry<String, Object> entry : parameters.entrySet())
			query.setParameter(entry.getKey(), entry.getValue());
		return query.getResultList();
	}


	@SuppressWarnings({ "unchecked" })
	public <T> T getSingleResultWithNamedQuery(String namedQueryName,
			Map<String, Object> parameters) {
		Query query = this.em.createNamedQuery(namedQueryName);
		for (Map.Entry<String, Object> entry : parameters.entrySet())
			query.setParameter(entry.getKey(), entry.getValue());
		return (T)query.getSingleResult();
	}
	@SuppressWarnings("unchecked")
	public <T> List<T> findWithNativeQuery(String sql, Class<T> type) {
		Query query = em.createNativeQuery(sql, type); 
		return query.getResultList();
	}
	
}
